﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace WebUpdateTool
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            dtUpdateTime.Value = DateTime.Now;
            dtUpdateTime.Format = DateTimePickerFormat.Custom;
            dtUpdateTime.CustomFormat = "yyyy-MM-dd HH:mm:ss";
            //ShowConfig();
            CreateConfigFile("app.config");
            //加载xml
            LoadFileConfig();
        }

        private void LoadFileConfig()
        {
            string xmlFilePath = Application.StartupPath + "\\updateFileConfig.xml";
            combSourceDir.Items.Clear();
            if (File.Exists(xmlFilePath))
            {
                XmlNodeList ls = Config.XMlTool.GetXmlNode();

                for (int i = ls.Count - 1; i >= 0; i--)
                {
                    XmlElement ele = (XmlElement)ls[i];
                    combSourceDir.Items.Add(ele.GetAttribute("key"));
                }
                if (combSourceDir.Items.Count <= 0)
                    return;

                combSourceDir.SelectedIndex = 0;
                XmlElement ele1 = (XmlElement)ls[0];
                ShowFileConfig(ele1);
            } 
        }
        private void ShowFileConfig(XmlElement ele)
        {
            labSourceDir.Text =ele.GetAttribute("key");
            labTargetDir.Text = ele.GetAttribute("destDir"); ;
            string lastUpdateTime =  ele.GetAttribute("updateTime");
            if (string.IsNullOrWhiteSpace(lastUpdateTime))
                dtUpdateTime.Value = DateTime.Now;
            else
                dtUpdateTime.Value = DateTime.Parse(lastUpdateTime);

            dtUpdateTime.Format = DateTimePickerFormat.Custom;
            dtUpdateTime.CustomFormat = "yyyy-MM-dd HH:mm:ss";
        }

        private void btnChoice_Click(object sender, EventArgs e)
        {
            btnOK.Enabled = true ;
            FolderBrowserDialog folderDlg = new FolderBrowserDialog();
            folderDlg.ShowDialog();
            labSourceDir.ForeColor = Color.Black;
            labSourceDir.Text = folderDlg.SelectedPath;
            combSourceDir.Text = folderDlg.SelectedPath;
           
        }

        private void btnSaveDir_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderDlg = new FolderBrowserDialog();
            if (labTargetDir.Text.Trim() != "")
            {
                folderDlg.SelectedPath = labTargetDir.Text;
            }
          
          
          
            if (folderDlg.ShowDialog() == DialogResult.OK)
            {
                labTargetDir.ForeColor = Color.Black;
                labTargetDir.Text = folderDlg.SelectedPath;
            }
          
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            btnOK.Enabled = false;
            if (string.IsNullOrWhiteSpace(labSourceDir.Text) || labSourceDir.Text == "请先选择需要更新的目录" || string.IsNullOrWhiteSpace(labTargetDir.Text) || labTargetDir.Text == "请先选择保存更新文件的目录")
            {
                labSourceDir.ForeColor = Color.Red;
                labSourceDir.Text = "请先选择需要更新的目录";
                labTargetDir.ForeColor = Color.Red;
                labTargetDir.Text = "请先选择保存更新文件的目录";

                return;
            }

            string source = labSourceDir.Text;
            string target = Path.Combine(labTargetDir.Text,dtUpdateTime.Value.ToString("yyyyMMddHHmmss"))+source.Substring(source.LastIndexOf("\\")+1);
            CreateDirectory(labTargetDir.Text);
            CreateDirectory(target);

            CheckDirectory(source, target);
            btnOK.Enabled = true;
        }


        private bool CheckDirectory(string dirPath, string target)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(dirPath); 
            DirectoryInfo[] arrDirInfo = dirInfo.GetDirectories();
            if (!IsDirectoryRule(dirInfo))
                return false;

            foreach (DirectoryInfo info in arrDirInfo)
            { 
               bool returnValue = CheckDirectory(info.FullName, target);

               if (!returnValue)
                   continue;

            
                this.CopyFile(info.FullName, target);
            }

            return true;
        }


        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="dirPath"></param>
        private void CreateDirectory(string dirPath)
        {
            try
            {
                if (!Directory.Exists(dirPath))
                {
                    Directory.CreateDirectory(dirPath);
                }
            }
            catch { }
        }


        /// <summary>
        /// 复制指定目录下的文件到指定目录下
        /// </summary>
        /// <param name="fileDir">源文件的目录</param>
        /// <param name="destDir">目标文件的目录</param>
        private void CopyFile(string fileDir,string destDir)
        {
            try
            {
                DirectoryInfo dir = new DirectoryInfo(fileDir);
               
                foreach (FileInfo file in dir.GetFiles())
                {
                    if (!IsExistRule(file))
                        continue;

                 CreateDirectory(dir.FullName.Replace(labSourceDir.Text,destDir));

                   string temp= file.FullName.Replace(labSourceDir.Text,destDir);
                    file.CopyTo(temp, true);
                }
            }
            catch { }
        }

        /// <summary>
        /// 判断文件的更新时间是否满足上次更新时间和文件后缀是否不包含在配置文化要求里
        /// </summary>
        /// <param name="fileInfo"></param>
        /// <returns>文件更新时间小于上次更新时间或后缀包含于配置文件中排除规则里的 返回false 否则返回true</returns>
        private bool IsExistRule(FileInfo fileInfo)
        {
            if (fileInfo.LastWriteTime < dtUpdateTime.Value)//满足时间条件
                return false;
             
            var arrRules = GetAppConfig("app", "Extensions");//满足文件类型的规则
             
            var result = arrRules.Where(t => t.ToLower() == fileInfo.Extension);
            if (result.Count() > 0)
                return false;

            return true;
        }

        /// <summary>
        /// 判断文件夹是否满足配置文件夹中的规定
        /// </summary>
        /// <param name="dirInfo"></param>
        /// <returns>文件夹名包含于配置文件夹中 返回false</returns>
        private bool IsDirectoryRule(DirectoryInfo dirInfo)
        {
            var arrDirRule = GetAppConfig("app", "dirRules");// GetAppSettingsValue("dirRules"); 
            //foreach(string temp in arrDirRule)
            //{
            //    if (temp == dirInfo.Name)
            //        return false;
            //}
            var dir = arrDirRule.Where(t => t.ToLower() == dirInfo.Name.ToLower());
            if (dir.Count() <=0)
                return true;
            else
                return false;


            //var dirs = dirInfo.GetDirectories();
            //if (dirs.Count() > 0) 
            //    return true;

            //var v = dirInfo.GetFiles(); 
            //var arr = from a in v where a.LastWriteTime >= dtUpdateTime.Value  select a;
            //if (arr.Count() <= 0)
            //    return false;

            //var files = v.SkipWhile (t => t.LastWriteTime > dtUpdateTime.Value && t.Extension !="");
           // return true;
        }

        private void SaveConfig()
        {
            UpdateAppSettings("sourceDir", labSourceDir.Text);
            UpdateAppSettings("destDir", labTargetDir.Text);
            UpdateAppSettings("updateTime", dtUpdateTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));
        }

        private void ShowConfig()
        {
            labSourceDir.Text = GetAppSettingsValue("sourceDir");
            labTargetDir.Text = GetAppSettingsValue("destDir");

            string lastUpdateTime = GetAppSettingsValue("updateTime");
          
            if (string.IsNullOrWhiteSpace(lastUpdateTime))
                dtUpdateTime.Value = DateTime.Now;
            else
                dtUpdateTime.Value = DateTime.Parse(lastUpdateTime);

            dtUpdateTime.Format = DateTimePickerFormat.Custom;
            dtUpdateTime.CustomFormat = "yyyy-MM-dd HH:mm:ss";

        }

        private void btnSaveConfig_Click(object sender, EventArgs e)
        {
            //SaveConfig();
            string xmlFilePath = Application.StartupPath + "\\updateFileConfig.xml";

            if (!File.Exists(xmlFilePath))
                Config.XMlTool.CreateXmlDoc("items", "1.0", "gb2312");

            Config.Config config = new Config.Config();
            config.updateTime = dtUpdateTime.Value.ToString("yyyy-MM-dd HH:mm:ss");
            config.destDir = labTargetDir.Text;
            config.sourceDir = labSourceDir.Text;

            Config.XMlTool.updateXMlNode("itmes", config);

            LoadFileConfig();
            combSourceDir_SelectedIndexChanged(sender, e);
          
            // XmlAttribute x = Config.XMLHelper.GetXmlAttribute(xmlFilePath, "//updateFileConfig//item", "key");
            //if (x != null && x.InnerText == labSourceDir.Text)
            //    return;


            //Config.XMLHelper.CreateXmlNodeByXPath(xmlFilePath, "//updateFileConfig", "item", "", "key", labSourceDir.Text);
            // Config.XMLHelper.CreateOrUpdateXmlNodeByXPath(xmlFilePath, "//updateFileConfig//item", "sourceDir", labSourceDir.Text);
            // Config.XMLHelper.CreateOrUpdateXmlNodeByXPath(xmlFilePath, "//updateFileConfig//item", "destDir", labTargetDir.Text);
            // Config.XMLHelper.CreateOrUpdateXmlNodeByXPath(xmlFilePath, "//updateFileConfig//item", "updateTime", dtUpdateTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));


        }



        public static string GetAppSettingsValue(string key)
        {
            ConfigurationManager.RefreshSection("appSettings");
            return ConfigurationManager.AppSettings[key] ?? string.Empty;
        }
        public static bool UpdateAppSettings(string key, string value)
        {
            var _config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (!_config.HasFile)
            {
                throw new ArgumentException("程序配置文件缺失！");
            }
            KeyValueConfigurationElement _key = _config.AppSettings.Settings[key];
            if (_key == null)
                _config.AppSettings.Settings.Add(key, value);
            else
                _config.AppSettings.Settings[key].Value = value;
            _config.Save(ConfigurationSaveMode.Modified);
            return true;
        }

        private void combSourceDir_SelectedIndexChanged(object sender, EventArgs e)
        {
            string value = combSourceDir.Text;
            XmlNodeList ls = Config.XMlTool.GetXmlNode();
            foreach(var item in ls)
            {
                XmlElement ele=(XmlElement)item;

                if(ele.GetAttribute("key") == value)
                {
                    ShowFileConfig(ele);
                    break;
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string key = combSourceDir.Text;
            XmlNodeList ls = Config.XMlTool.GetXmlNode();
            foreach (XmlNode item in ls)
            {
                XmlElement ele = (XmlElement)item;

                if (ele.GetAttribute("key") == key)
                {
                    Config.XMlTool.DeleteXMLNode(key);
                    combSourceDir.Items.Remove(key);
                    if (combSourceDir.Items.Count <= 0)
                    {
                        combSourceDir.Text = "";
                        labSourceDir.Text = "";
                        labTargetDir.Text = "";
                    }
                    else if(combSourceDir.SelectedIndex >0 )
                    {
                        combSourceDir.SelectedIndex = combSourceDir.SelectedIndex - 1;
                    }
                    else
                    {
                        combSourceDir.SelectedIndex = 0;

                    }

                    break;
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (labTargetDir.Text == "" || labTargetDir.Text == "请先选择保存更新文件的目录")
                return;

            System.Diagnostics.Process.Start("Explorer.exe", labTargetDir.Text);
        }

        private void CreateConfigFile(string fileName)
        {
            string filePath = Application.StartupPath + "\\" + fileName;
            if(!File.Exists(filePath))
            {
                string configInfo = "Extensions=.cs|.pdb|.csproj|.user|.config|.sln|.suo\n"+
                                    "dirRules=obj|.svn|QianTuClient.Biz|QianTuClient.Model|QianTuClient_UM.Biz|QianTuClient_UM.Model|lib\n" ;
                File.AppendAllText(filePath, configInfo,ASCIIEncoding.Unicode);
            }
        }

        public static List<string> GetAppConfig(string ConfigName,string itemName)
        {
            string filePath = Application.StartupPath + "\\" + ConfigName+".config";
            string content = File.ReadAllText(filePath, ASCIIEncoding.Unicode);
            var arrContent = content.Split(new string[]{ "\n" }, StringSplitOptions.RemoveEmptyEntries);
            if(arrContent.Length >0)
            {
                foreach(var item in arrContent)
                {
                    var t = item.Split('=');
                    if(t[0]==itemName)
                    {
                        var result = t[1].Split('|');
                        if (result.Length > 0)
                            return result.ToList<string>();
                        else
                            return new List<string>();
                    }
                }

            }

            return new List<string>();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if(File.Exists(Application.StartupPath+"\\"+"app.config"))
            { 
                 CongigSetting configSettring =new CongigSetting();
                 configSettring.ShowDialog();
            }
            else 
            MessageBox.Show("配置文件已丢失，请重新启动工具");
        }

        private void button4_Click(object sender, EventArgs e)
        {

        }
      

    }
}
